
package com.bluelinelabs.conductor.conductor;

import ohos.aafwk.content.Intent;
import ohos.agp.components.ComponentContainer;
import ohos.app.AbilityContext;

import com.bluelinelabs.conductor.conductor.internal.TransactionIndexer;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

/**
 * lipeiquan
 *
 * @since 2021-05-06
 */
public class ControllerHostedRouter extends Router {

    private boolean isDetachFrozen;
    private Controller hostController;
    private int hostId;
    private String tag;

    @Override
    TransactionIndexer getTransactionIndexer() {
        Router rootRouter = getRootRouter();
        if (rootRouter == this) {
            String debugInfo;
            if (hostController != null) {
                debugInfo = String.format(Locale.ENGLISH, "%s (attached? %b, destroyed? %b, parent: %s)",
                    hostController.getClass().getSimpleName(), hostController.isAttached(), hostController.isBeingDestroyed, hostController.getParentController());
            } else {
                debugInfo = "null host controller";
            }
            throw new IllegalStateException("Unable to retrieve TransactionIndexer from " + debugInfo);
        } else {
            return getRootRouter().getTransactionIndexer();
        }
    }

    @Override
    Router getRootRouter() {
        if (hostController != null && hostController.getRouter() != null) {
            return hostController.getRouter().getRootRouter();
        } else {
            return this;
        }
    }

    @Override
    List<Router> getSiblingRouters() {
        List<Router> list = new ArrayList<>();
        list.addAll(hostController.getChildRouters());
        list.addAll(hostController.getRouter().getSiblingRouters());
        return list;
    }

    @Override
    void unregisterForActivityResults(String instanceId) {
        if (hostController != null && hostController.getRouter() != null) {
            hostController.getRouter().unregisterForActivityResults(instanceId);
        }
    }

    @Override
    void registerForActivityResult(String instanceId, int requestCode) {
        if (hostController != null && hostController.getRouter() != null) {
            hostController.getRouter().registerForActivityResult(instanceId, requestCode);
        }
    }

    ControllerHostedRouter() {
    }

    ControllerHostedRouter(int hostId, String tag) {
        this.hostId = hostId;
        this.tag = tag;
    }

    final void setHostController(Controller controller) {
        if (hostController == null) {
            hostController = controller;
        }
    }


    final void setDetachFrozen(boolean frozen) {
        isDetachFrozen = frozen;
        for (RouterTransaction transaction : backstack) {
            transaction.controller.setDetachFrozen(frozen);
        }
    }

    final void setHostContainer(Controller controller, ComponentContainer container) {
        if (hostController != controller || this.container != container) {
            removeHost();

            if (container instanceof ControllerChangeHandler.ControllerChangeListener) {
                addChangeListener((ControllerChangeHandler.ControllerChangeListener) container);
            }

            hostController = controller;
            this.container = container;

            for (RouterTransaction transaction : backstack) {
                transaction.controller.setParentController(controller);
            }

            watchContainerAttach();
        }
    }

    String getTag() {
        return tag;
    }

    @Override
    public AbilityContext getActivity() {
        return hostController != null ? hostController.getActivity() : null;
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (hostController != null && hostController.getRouter() != null) {
            hostController.getRouter().onActivityResult(requestCode, resultCode, data);
        }
    }

    @Override
    void destroy(boolean popViews) {
        setDetachFrozen(false);
        super.destroy(popViews);
    }

    final void removeHost() {
        if (container != null && container instanceof ControllerChangeHandler.ControllerChangeListener) {
            removeChangeListener((ControllerChangeHandler.ControllerChangeListener) container);
        }

        final List<Controller> controllersToDestroy = new ArrayList<>(destroyingControllers);
        for (Controller controller : controllersToDestroy) {
            if (controller.getView() != null) {
                controller.detach(controller.getView(), true, false);
            }
        }
        for (RouterTransaction transaction : backstack) {
            if (transaction.controller.getView() != null) {
                transaction.controller.detach(transaction.controller.getView(), true, false);
            }
        }

        prepareForContainerRemoval();
        container = null;
    }

    int getHostId() {
        return hostId;
    }

    @Override
    boolean hasHost() {
        return hostController != null && container != null;
    }

    @Override
    void invalidateOptionsMenu() {

    }

    @Override
    void performControllerChange(RouterTransaction to, RouterTransaction from, boolean isPush) {
        super.performControllerChange(to, from, isPush);

        // If we're pushing a transaction that will detach controllers to an unattached child
        // router, we need mark all other controllers as NOT needing to be reattached.
        if (to != null && !hostController.isAttached()) {
            if (to.pushChangeHandler() == null || to.pushChangeHandler().removesFromViewOnPush()) {
                for (RouterTransaction transaction : backstack) {
                    transaction.controller.setNeedsAttach(false);
                }
            }
        }
    }

    @Override
    public void setBackstack(List<RouterTransaction> newBackstack, ControllerChangeHandler changeHandler) {
        if (isDetachFrozen) {
            for (RouterTransaction transaction : newBackstack) {
                transaction.controller.setDetachFrozen(true);
            }
        }
        super.setBackstack(newBackstack, changeHandler);
    }

    @Override
    protected void pushToBackstack(RouterTransaction entry) {
        if (isDetachFrozen) {
            entry.controller.setDetachFrozen(true);
        }
        super.pushToBackstack(entry);
    }


}
